<script setup>
import { ref, onMounted, getCurrentInstance, toRefs } from 'vue'
import { addTokenToUrl } from '../../../utils/token'
import { jumpHttp, isMobile, isWeixinMini } from '../../../utils/host'
import { stt } from '../../../service/api'

// sendInput发送信息
// stopAi: 触摸语音按钮，停止说话和动作
const Emit = defineEmits(['sendInput', 'stopAi']) // sendInput：发送信息 ； stopAi: 触摸语音按钮，停止说话和动作
const { appContext } = getCurrentInstance()
const proxy = appContext.config.globalProperties
const config = proxy.$config
const tags = ref([]) // 猜你想问列表
const inputVal = ref('') // input 框value

const props = defineProps({
  isAnswering: {
    type: Boolean
  },
  isPending: {
    type: Boolean
  },
  lan: {
    type: String,
    default: ''
  }
})

const { isPending, isAnswering, lan } = toRefs(props)

// 浏览器通用录制语音方法
const canRecord = ref(false)
const browserRecord = {
  rec: null,
  recBlob: null,
  /** 调用open打开录音请求好录音权限**/
  recOpen: () => {
    browserRecord.rec = null
    browserRecord.recBlob = null
    let wave
    const newRec = Recorder({
      type: 'mp3',
      sampleRate: 16000,
      bitRate: 16, // mp3格式，指定采样率hz、比特率kbps，其他参数使用默认配置；注意：是数字的参数必须提供数字，不要用字符串；需要使用的type类型，需提前把格式支持文件加载进来，比如使用wav格式需要提前加载wav.js编码引擎
      onProcess: function (
        buffers,
        powerLevel,
        bufferDuration,
        bufferSampleRate,
        newBufferIdx,
        asyncEnd
      ) {
        wave.input(buffers[buffers.length - 1], powerLevel, bufferSampleRate)
      }
    })
    newRec.open(
      function () {
        // 打开麦克风授权获得相关资源
        browserRecord.rec = newRec
        canRecord.value = true
        wave = Recorder.WaveView({ elem: '#recording' })
        console.log('已打开录音，可以点击录制开始录音了')
      },
      function (msg, isUserNotAllow) {
        // 用户拒绝未授权或不支持
        proxy.$toast({
          message: '当前环境不支持语音输入'
        })
      }
    )
  },
  /** 关闭录音，释放资源**/
  recClose: () => {
    if (browserRecord.rec) {
      browserRecord.rec.close()
      console.log('已关闭')
    } else {
      console.log('未打开录音')
    }
  },
  /** 开始录音**/
  recStart: () => {
    // 打开了录音后才能进行start、stop调用
    if (browserRecord.rec && Recorder.IsOpen()) {
      browserRecord.recBlob = null
      console.log('已开始录音...')
      browserRecord.rec.start()
    } else {
      console.log('未打开录音')
    }
  },
  /** 结束录音，得到音频文件**/
  recStop: () => {
    if (!(browserRecord.rec && Recorder.IsOpen())) {
      console.log('未打开录音')
      return
    }
    browserRecord.rec.stop(
      function (blob, duration) {
        browserRecord.recBlob = blob
        const time = Date.now()
        const file = new File([blob], `${time}.mp3`, {
          type: 'audio/mp3',
          lastModified: time
        })
        const data = {
          file,
          language: lan.value
        }
        stt(data)
          .then((res) => {
            res = JSON.parse(res)
            console.log(res)
            if (res.status === 20000000) {
              // Emit('sendInput', res.result)
              inputVal.value = res.result
              inputRef.value.innerText = res.result
            } else {
              proxy.$toast('语音识别失败')
            }
          })
          .catch(() => {
            proxy.$toast('语音识别失败')
          })
      },
      function (msg) {
        console.log('录音失败')
      }
    )
  },
  /** 结束录音**/
  recCancel: () => {
    if (!(browserRecord.rec && Recorder.IsOpen())) {
      console.log('未打开录音')
      return
    }
    browserRecord.rec.stop(
      function (blob, duration) {
        browserRecord.recBlob = null
      },
      function (msg) {
        console.log('录音失败')
      }
    )
  }
}
const showSpeechBox = ref(false)
const isSpeech = ref(false)
const startRecord = () => {
  if (!isSpeech.value) {
    showSpeechBox.value = true
    browserRecord.recStart()
    isSpeech.value = true
  } else {
    endRecord()
  }
}

const endRecord = () => {
  showSpeechBox.value = false
  browserRecord.recStop()
  isSpeech.value = false
}

// 获取运营位配置列表
const tagsRef = ref()
const getTags = () => {
  tags.value = config.omConfigs || []
}

// 运营位跳转
const jump = (item) => {
  Emit('stopAi')
  if (!item.link) {
    proxy.$toast('当前服务正在和学校建设中，请耐心等待吧')
    return
  }
  setTimeout(() => {
    if (item.type === 4) {
      // 跳转app应用 wanxiao://......
      if (!isMobile()) {
        proxy.$toast('请在移动端使用此功能')
        return
      }
      window.location.href = item.link
    } else if (item.type === 2) {
      if (!isWeixinMini()) {
        proxy.$toast('请在微信小程序环境使用此功能')
        return
      }
      wx.miniProgram.navigateTo({
        url: item.link
      })
    } else if (item.type === 3) {
      // 跳转http链接
      item.link = !isMobile() ? item.pcLink : item.link
      const url =
        item.appendToken === 1
          ? item.link
          : addTokenToUrl(
            item.link,
            item.putTokenName || 'token',
            item.gainTokenName || 'token'
          )
      if (url === 'invalid url') {
        proxy.$toast('地址解析失败，请检查配置')
        return
      }
      jumpHttp(url)
    }
  }, 50)
}

// 发送问题
const sendInput = () => {
  if (isAnswering.value || isPending.value) {
    proxy.$toast({
      message: '请等待回答结束'
    })
    return
  }
  if (inputVal.value) {
    Emit('sendInput', inputVal.value)
    inputRef.value.innerText = ''
    inputVal.value = ''
    suggetsList.value = []
  }
}

const onInput = (e) => {
  inputVal.value = e.target.innerText
  // 注释实时搜索
  // if (inputVal.value) {
  //   search()
  // } else {
  //   suggetsList.value = []
  // }
}

const onBlur = () => {
  // 注释实时搜索
  // setTimeout(() => {
  //   suggetsList.value = []
  // }, 500)
}

const suggetsList = ref([])
const search = () => {
  setTimeout(() => {
    suggetsList.value = []
    if (inputVal.value) {
      const ret = [
        '如何充值校园卡？',
        '如何充值学费到银行卡？',
        '公司充值宿舍wifi费用？'
      ]
      ret.forEach((item) => {
        const replaceReg = new RegExp(inputVal.value, 'ig')
        const replaceString = `<span style="color: #0B9EFC"> ${inputVal.value} </span>`
        let html = ''
        html = item.replace(replaceReg, replaceString)
        suggetsList.value.push({
          name: item,
          html
        })
      })
    } else {
      suggetsList.value = []
    }
  }, 2000)
}

const sendSuggest = (item) => {
  sendInput(item.name)
  suggetsList.value = []
}

const inputRef = ref()

const keyupEnter = (e) => {
  if (e.keyCode === 13) {
    if (e) e.preventDefault()
    sendInput()
  }
}

const textFormat = (e) => {
  e.preventDefault()
  let text
  const clp = (e.originalEvent || e).clipboardData
  if (clp === undefined || clp === null) {
    text = window.clipboardData.getData('text') || ''
    if (text !== '') {
      if (window.getSelection) {
        const newNode = document.createElement('span')
        newNode.innerHTML = text
        window.getSelection().getRangeAt(0).insertNode(newNode)
      } else {
        document.selection.createRange().pasteHTML(text)
      }
    }
  } else {
    text = clp.getData('text/plain') || ''
    if (text !== '') {
      document.execCommand('insertText', false, text)
    }
  }
}

onMounted(() => {
  browserRecord.recOpen()
  // getTags()
  // tagsRef.value.addEventListener('wheel', (e) => {
  //   e.preventDefault()
  //   const step = 40
  //   if (e.deltaY < 0) {
  //     tagsRef.value.scrollLeft -= step
  //   } else {
  //     tagsRef.value.scrollLeft += step
  //   }
  // })
  inputRef.value.addEventListener('keydown', keyupEnter)
  inputRef.value.addEventListener('paste', (e) => {
    inputRef.value.paste = true
    textFormat(e)
  })
})
</script>

<template>
  <div class="input-box">
    <!-- <div class="tag-wrapper">
      <div class="tags" ref="tagsRef">
        <span
          class="tag"
          v-for="item in tags"
          :key="item.id"
          @click.stop="jump(item)"
        >{{ item.name }}</span>
      </div>
    </div> -->
    <div class="suglist" v-if="suggetsList.length">
      <div
        class="item"
        v-for="(item, index) in suggetsList"
        :key="index"
        v-html="item.html"
        @click="sendSuggest(item)"
      />
    </div>
    <div class="input-wrapper">
      <div
        ref="inputRef"
        class="textarea"
        contenteditable="true"
        placeholder="试试与我互动吧~"
        @input="onInput"
        @blur="onBlur"
      />
      <span v-if="canRecord" class="voice" @click="startRecord" />
      <span class="send" @click="sendInput" />
    </div>
  </div>
  <div class="speech-box" :class="{'active': showSpeechBox}">
    <div id="recording" />
  </div>
</template>

<style lang="less">
.input-box {
  width: 100%;
  height: 138px;
  position: absolute;
  .suglist {
    width: 100%;
    left: 0;
    bottom: 115px;
    position: absolute;
    background: #ffffff;
    border-radius: 4px;
    font-size: 16px;
    padding: 24px 11px;
    .item {
      margin-bottom: 16px;
      cursor: pointer;
    }
    .item:last-child {
      margin-bottom: 0;
    }
  }
  .tag-wrapper {
    width: 100%;
    font-size: 14px;
    color: #333333;
    .tags {
      overflow-x: auto;
      word-break: keep-all;
      white-space: nowrap;
      .tag {
        display: inline-block;
        background: rgba(253, 252, 255, 0.8);
        border-radius: 24px;
        word-break: keep-all;
        white-space: nowrap;
        margin-right: 8px;
        padding: 8px 25px;
        cursor: pointer;
        border: 1px solid #dbdbdb;
        &:hover {
          background-color: #dbdbdb;
        }
      }
      .tag:last-child {
        margin-right: 0;
      }
    }
  }
  .input-wrapper {
    height: 100%;
    background: #fbfbfb;
    border-radius: 8px;
    border: 1px solid #4D94E7;
    position: relative;
    .textarea {
      outline: none;
      padding: 16px 16px 52px 16px;
      height: 100%;
      font-size: 14px;
    }
    .textarea:empty:before {
      content: "试试与我互动吧~";
      color: #bab7d2;
      cursor: text;
      font-size: 14px;
    }
    span {
      display: flex;
      width: 48px;
      height: 32px;
      cursor: pointer;
      position: absolute;
      border-radius: 18px;
      justify-content: center;
      align-items: center;
    }
    .send {
      background-image: url("../../../assets/img/send.png");
      background-size: 100% 100%;
      right: 16px;
      bottom: 14px;
    }
    .voice {
      width: 25px;
      height: 25px;
      background-image: url("../../../assets/img/ps.png");
      background-size: 100% 100%;
      right: 80px;
      bottom: 16px;
    }
  }
}
.speech-box {
  width: 200px;
  height: 80px;
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  background-color: #7a92ad;
  border-radius: 10px;
  z-index: -999;
  &.active{
    z-index: 1;
  }
  #recording{
    width: 100%;
    height: 100%;
  }
}
@keyframes load1 {
  0%,
  100% {
    height: 20px;
    background-color: #ffffff;
  }
  50% {
    height: 40px;
    background-color: #f9f5f5;
  }
}
</style>
